<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>

        #title{
            background: orange;
        }
    </style>
</head>
<body>
    <div>
        <h3 id="title"  demo="wh2107-daydayup" class="one demo" >封装模拟 jQuery </h3>
        <ul class="list">
            <li>item_01</li>
            <li>item_02</li>
            <li>item_03</li>
            <li>item_04</li>
            <li>item_05</li>
            <li>item_06</li>
            <li>item_07</li>
            <li>item_08</li>
            <li>item_09</li>
            <li>item_10</li>
        </ul>
        <p>
            <input type="text" class="inp" value="Are you oK....">
        </p>
        <p>
            <label for="tips"> 
                <input type="checkbox" id="tips" >  请先同意我的霸王条款.
            </label>
        </p>
        <div class="box">
            <button class="sethtml">设置html</button>
            <button class="gethtml">获取html</button>
            <button class="show">点击显示</button>
            <button class="hide">点击隐藏</button>
            <button class="setwidth">设置宽度</button>
            <button class="getwidth">获取宽度</button>
            <button class="css">css操作</button>
            <button class="attr">attr</button>
            <button class="prop">prop</button>
            <button class="eq">eq</button>
            <button class="siblings">siblings</button>

        </div>
    </div>

    <script>
        // jquery 通过原生JS封装的操作DOM 的 一个 JS框架   模拟DOM操作(增删改查)

        // 面向过程
        // 获取元素对象
        // 单个元素 直接操作
        // var h3 = document.getElementById("title");
        // h3.innerHTML = "hello world";

        // 多个元素 
        // var lilist = document.querySelectorAll("li");
        // for(var i=0;i<lilist.length;i++){
        //     var ele = lilist[i];
        //     ele.innerHTML = "hello wuhan2107"
        // }

        // var lilist = document.querySelectorAll("li");
        // function setHtml(index,text){   // text 表示需要修改的值
        //     for(var i=0;i<lilist.length;i++){
        //         var ele = lilist[i];
        //         if(i==index){
        //             ele.innerHTML = text 
        //         }
        //     }
        // }
        // setHtml(2,"abc123123123")

        // // 查找元素 
        // function getDom(index){
        //     var lilist = document.querySelectorAll("li");
        //     if(!index){
        //         return lilist[0]   // jquery 查找元素 默认都是找第一个 
        //     }
        //     var dom = [];   //  document.querySelectorAll  jquery是把查出来的元素放到一个数组 
        //     lilist.forEach((item,i)=>{
        //         if(i==index){
        //             dom.push(lilist[index]);  
        //         }
        //     })
        //     return dom;
        // }

        // var dom2 = getDom(2);
        // console.log(dom2)


        // $().html().text().eq().find().attr()
        // $.text()
        // $.val()
        // $ ==> jquery 
        // 面向对象
        
        // 单例模式 
        function GetEle(selector){
            this.eles = document.querySelectorAll(selector)
        }

        GetEle.prototype.html = function(text){
            if(arguments.length>= 1){   // 有参数 
                for(var i=0;i<this.eles.length;i++){
                    var ele = this.eles[i];
                    ele.innerHTML = text;
                }
                return this;
            }else{
                // 没有传参数  
                return this.eles[0].innerHTML;
            }
        }
        GetEle.prototype.text = function(arg){
            if(arguments.length>= 1){   // 有参数 
                for(var i=0;i<this.eles.length;i++){
                    var ele = this.eles[i];
                    ele.textContent = arg;
                }
                return this;
            }else{
                // 没有传参数  
                return this.eles[0].textContent;
            }
        }
        GetEle.prototype.val = function(value){
            if(arguments.length>= 1){   // 有参数 
                for(var i=0;i<this.eles.length;i++){
                    var ele = this.eles[i];
                    ele.value = value;
                }
                return this;
            }else{
                // 没有传参数  
                return this.eles[0].value 
            }
        }
        GetEle.prototype.hide = function(){
            // this ==> GetEle => 实例化的对象 
            for(var i=0;i<this.eles.length;i++){
                var ele = this.eles[i];
                ele.style.display = 'none';
            }
            return this;
        }
        GetEle.prototype.show = function(){
            // this ==> GetEle => 实例化的对象 
            for(var i=0;i<this.eles.length;i++){
                var ele = this.eles[i];
                ele.style.display = 'block';
            }
            return this;
        }

        // 循环实例化对象中的集合 this.eles  每次循环时候传入 回调函数 
        GetEle.prototype.each = function(fn){  // fn 传入一个函数 
            for(var i=0;i<this.eles.length;i++){
                var item = this.eles[i];
                var index = i;
                // fn.call();
                // fn(item,index);

                // fn.call(this,arg1,arg2,arg3)  call 改变this的指向 
                fn.call(this,item,index,this.eles);

                // fn.call(this,index,item,this.eles);
                // 注意  jquery each 第一个参数是下表 第二个才是当前循环的元素

            }
            return this;
        }

        GetEle.prototype.click = function(fn){
            // for(var i=0;i<this.eles.length;i++){
            //     var ele = this.eles[i];
            //     ele.addEventListener("click",fn);  // DOM2          DOM0 
            // }
            // this.each((ele,index)=>{
            //     ele.addEventListener("click",fn);
            // })
            this.on("click",fn);
            return this;
        }

        GetEle.prototype.on = function(eventType,fn){
            this.each(ele=>{
                if(ele.addEventListener){   
                    // 普通正常的浏览器 
                    ele.addEventListener(eventType,fn)
                }else{
                    ele.attachEvent('on'+eventType,fn)   // IE 
                }
            })
            return this;
        }

        // width()
        // width()  获取元素的宽度
        // width(200px) 设置元素的宽度 
        GetEle.prototype.width = function(arg){
            if(arguments.length>= 1){
                this.each(ele=>{
                    // 200px px  pt(物理像素) em rem vw vh  %  有单位的就直接拼接 
                    // 200  没有单位      默认px 
                    var unitReg = /^\d+(px|pt|vw|vh|rem|%|em)$/
                    if(unitReg.test(arg)){
                        ele.style.width = arg;
                    }else{
                        ele.style.width = arg + "px";
                    }
                })
                return this;
            }else{
                // 返回宽度值
                // return this.eles[0].style.width;

                // 默认返回第一个 
                // return parseFloat(getStyle(this.eles[0],'width'))
                return parseFloat(this.getStyle("width"))
            }
        }


        GetEle.prototype.height = function(arg){
            if(arguments.length>= 1){
                this.each(ele=>{
                    // 200px px  pt(物理像素) em rem vw vh  %  有单位的就直接拼接 
                    // 200  没有单位      默认px 
                    var unitReg = /^\d+(px|pt|vw|vh|rem|%|em)$/
                    if(unitReg.test(arg)){
                        ele.style.height = arg;
                    }else{
                        ele.style.height = arg + "px";
                    }
                })
                return this;
            }else{
                // 默认返回第一个 
                return parseFloat(this.getStyle("height"))
            }
        }

        GetEle.prototype.getStyle = function(attr){
            var ele  = this.eles[0]  // 默认返回第一个
            if(window.getComputedStyle){
                return window.getComputedStyle(ele)[attr];
            }else{
                return ele.currentStyle[attr];
            }
        }

        // css()   获取或者设置某个css
        // css("color");  获取字体颜色
        // css("color",'red') 设置字体颜色 

        // css("color")   获取
        // css({color:'red',fontSize:'16px'})  同时 设置 多个样式   
        GetEle.prototype.css =  function(key,value){
            if(arguments.length>= 2){
                // 设置字体颜色 
                this.each(ele=>{
                    // ele.style.width = value;
                    ele.style[key] = value ;
                })
                return this; // 把实例话对象返回 
            }else if(arguments.length==1){
                // 获取css
                // 判断是不是对象 
                if(Object.prototype.toString.call(key)==='[object Object]'){    
                    // {color:'red',fontSize:'16px',float:'left',width:'200px'}
                    // key 是一个对象 
                    for(var name in key){
                        console.log(name)
                        // this.each(ele=>{
                        //     ele.style[name] = key[name] ;
                        // })
                        this.css(name,key[name]);   // 递归自调用 
                    }
                    return this;
                }else{
                    return this.getStyle(key);
                }
            }
        }

        // style行内样式 

        // 非行内样式 css
        function getStyle(ele,attr){
            if(window.getComputedStyle){
                return window.getComputedStyle(ele)[attr];
            }else{
                return ele.currentStyle[attr];
            }
        }

        // getAttribute  获取属性
        // setAttribute  设置属性 
        // attr 
        // attr(key,val)  // 设置  setAttribute(Key,val)
        // attr(key)   获取  getAttribute(key)
        GetEle.prototype.attr=function(key,val ){
            if(arguments.length>= 2){
                this.each(ele=>{
                    ele.setAttribute(key,val)
                })
                return this;
            }else if(arguments.length==1){
                return this.eles[0].getAttribute(key)
            }
        }

        // prop  
        // prop 获取或者设置当前元素节点的属性  ele.innerHTML ele.classList 
        // prop(key,val)
        // prop('className','one')    ele.className = "one"

        // prop(key)   一个参数就直接获取值
        // prop("className")
        // prop('checked')
        // prop("checked",false)

        GetEle.prototype.prop =function(key,val ){
            if(arguments.length>= 2){
                this.each(ele=>{
                    ele[key] = val;
                })
                return this;
            }else if(arguments.length==1){
                return this.eles[0][key]
            }
        }

        // 添加class 
        GetEle.prototype.addClass = function(){   // 参数的个数不确定
            var arg = arguments;  // 数组 
            console.log(arg)
            this.each(ele=>{
                ele.classList.add(...arg); // 数组展开 
            })
            return this;
        }

        GetEle.prototype.removeClass = function(){
            var arg = arguments;  // 数组 
            this.each(ele=>{
                ele.classList.remove(...arg); // 数组展开 
            })
            return this;
        }

        // 链式操作  方法的返回值 依然是一个实例化对象  (对应的构造函数)   return this 为了链式操作 
        // var p = new Promise(())
        // p.then().then().then().then().catch().finally
        // str.replace().replace().replace()

        // eq  
        // eq(1)  
        // $(".list li").eq(1).css().height()
        GetEle.prototype.eq = function(index){
            var ele = this.eles[index];      // 通过下表获取对应的元素 
            this.eles = [ele];     //  把获取到的元素重新的放到一个集合   单个元素也要放到一个集合里面去  
            return this;    
        }
        
        // siblings 兄弟节点 返回的是 被选中元素的 以外的所有的兄弟同级元素 (返回新的实例化对象)
        // $(".list li").eq(1).siblings().css().height()
        GetEle.prototype.siblings = function(){ 
            var ele = this.eles[0];
            var parentEle = ele.parentElement; // 父亲节点
            var children = parentEle.children;  // 子元素   伪数组

            var nodes = Array.from(children).filter(item=>item!=ele);    // 当前元素的兄弟节点  
            this.eles = nodes; 
            return this;
        }


        // 对 GetEle 二次封装  模仿jquery 快速创建一个实例化对象  
        function $(selector){
            return new GetEle(selector)
        }
        // hide show 
        // $(".list li")  ==> 实例化对象 

        // $(".list li").html('zkl-zkl')
        // $(".inp").val("hello - hello - wuhan")

        $(".list li").click(function(){
            // this ==> 标签 
            console.log(this)
            console.log(this.innerHTML)
            // console.log($('.list li').html())
        })
        
        $(".inp").on("input",function(){
            console.log(this.value)
        })

        $(".sethtml").on("click",function(){
            $("#title").html("hello - wh2107")
        })

        $(".gethtml").on("click",function(){
            console.log($("#title").html())
        })

        $(".show").on("click",function(){
            $("#title").show()
        })

        $(".hide").on("click",function(){
            $("#title").hide()
        })

        $(".getwidth").on('click',function(){
            console.log($("#title").width())
            console.log($("#title").height())

        })

        $(".setwidth").on('click',function(){
            $("#title").width(200)
            $("#title").height(50)
        })
        // css width height 
        
        $('.css').on("click",function(){
            console.log($("#title").css("width"))
            console.log($("#title").css("background"))

            // $("#title").css("color",'red');

            $("#title").css({
                color:'red',
                width:'200px',
                height:'200px',
                fontSize:'40px',
                border:"4px solid blue"
            });
        })

        $(".attr").on('click',function(){
            console.log($("#title").attr('demo') )
            $("#title").attr("myid","0831")
        })

        $(".prop").on("click",function(){
            // 节点私有属性 
            // $("#title").prop("className","news")  
            // // attrbiute 自定义属性  
            // console.log($("#title").prop("id"))      
            // console.log($("#title").prop("demo")) 

            // if($("#tips").prop("checked")){
            //     $("#tips").prop("checked",false);
            // }else{
            //     $("#tips").prop("checked",true);
            // }
           
            // $("#title").addClass("one1","one2","one3")
            $("#title").removeClass("one","demo")
        })

        $(".eq").on("click",function(){
            console.log($('.list li').eq(2))
            $(".list li").eq(2).css({color:'red',background:"pink"})
            $(".list li").eq(3).css("color","green");
        })


        $(".siblings").on("click",function(){
            $(".list li")
            .eq(2).css({color:"red",background:"pink"}).height(100).html("hello 2107").addClass("demo2107")
            .siblings()
            .css({
                color:"#f50",
                background:"#123456",
            })
            .width(100);
        })

    </script>
    
    
</body>
</html>
